//
//  buyCardTest.c
//  
//
//  Created by Preston Skaggs on 3/10/14.
//  This tests buyCard() in dominion.c with some random inputs
//
//

#include <stdio.h>
#include <stdlib.h>
#include "dominion.h"
#include "rngs.h"
#include "dominion_helpers.h"
#include <assert.h>
#include <time.h>
#include <math.h>
#include <string.h>

#define NUM_TESTS 1000
#define NUM_K_CARDS 10
#define NUM_CARD_TYPES (treasure_map+1)
#define TRUE 1
#define FALSE 0
#define MIN_PLAYERS 2

/*************************************
 Prototypes
 ************************************/
int initializeGameRandom(int numPlayers, int kingdomCards[10], int randomSeed,struct gameState *state);
void selectKingdomCards(int randomSeed, int kingCards[NUM_K_CARDS]);
double randGen();

/*************************************
 Supporting Functions
 ************************************/

/*------------------------------------
 Randomly Select Kingdom Cards
 -----------------------------------*/
//This is taken from interface.c
void selectKingdomCards(int randomSeed, int kingCards[NUM_K_CARDS]) {
    int i, used, card, numSelected = 0;
    SelectStream(1);
	PutSeed((long)randomSeed);
    
	
    while(numSelected < NUM_K_CARDS) {
        used = FALSE;
        card = floor(Random() * NUM_CARD_TYPES);
        if(card < adventurer) continue;
        for(i = 0; i < numSelected; i++) {
            if(kingCards[i] == card) {
                used = TRUE;
                break;
            }
        }
        if(used == TRUE) continue;
        kingCards[numSelected] = card;
        numSelected++;
    }
}
/*------------------------------------
 Random initializer
 -----------------------------------*/
//This is dominion.c's initializeGame function to which I added some randomness
int initializeGameRandom(int numPlayers, int kingdomCards[10], int randomSeed,struct gameState *state) {
    
    int i;
    int j;
    int it;
    //set up random number generator
    SelectStream(1);
    PutSeed((long)randomSeed);
    
    //check number of players
    if (numPlayers > MAX_PLAYERS || numPlayers < 2)
    {
        return -1;
    }
    
    //set number of players
    state->numPlayers = numPlayers;
    
    //check selected kingdom cards are different
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10; j++)
        {
            if (j != i && kingdomCards[j] == kingdomCards[i])
            {
                return -1;
            }
        }
    }
    
    
    //initialize supply
    ///////////////////////////////
    
    //set number of Curse cards
    if (numPlayers == 2)
    {
        state->supplyCount[curse] = Random()*10;
    }
    else if (numPlayers == 3)
    {
        state->supplyCount[curse] = Random()*20;
    }
    else
    {
        state->supplyCount[curse] = Random()*30;
    }
    
    //set number of Victory cards
    if (numPlayers == 2)
    {
        state->supplyCount[estate] = Random()*8;
        state->supplyCount[duchy] = Random()*8;
        state->supplyCount[province] = Random()*8;
    }
    else
    {
        state->supplyCount[estate] = Random()*12;
        state->supplyCount[duchy] = Random()*12;
        state->supplyCount[province] = Random()*12;
    }
    
    //set number of Treasure cards
    state->supplyCount[copper] = Random()*(60 - (7 * numPlayers));
    state->supplyCount[silver] = Random()*40;
    state->supplyCount[gold] = Random()*30;
    
    //set number of Kingdom cards
    for (i = adventurer; i <= treasure_map; i++)       	//loop all cards
    {
        for (j = 0; j < 10; j++)           		//loop chosen cards
        {
            if (kingdomCards[j] == i)
            {
                //check if card is a 'Victory' Kingdom card
                if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens)
                {
                    if (numPlayers == 2){
                        state->supplyCount[i] = Random()*8;
                    }
                    else{ state->supplyCount[i] = Random()*12; }
                }
                else
                {
                    state->supplyCount[i] = Random()*10;
                }
                break;
            }
            else    //card is not in the set choosen for the game
            {
                state->supplyCount[i] = -1;
            }
        }
        
    }
    
    ////////////////////////
    //supply intilization complete
    
    //set player decks
    for (i = 0; i < numPlayers; i++)
    {
        state->deckCount[i] = 0;
        for (j = 0; j < 3; j++)
        {
            state->deck[i][j] = estate;
            state->deckCount[i]++;
        }
        for (j = 3; j < 10; j++)
        {
            state->deck[i][j] = copper;
            state->deckCount[i]++;
        }
    }
    
    //shuffle player decks
    for (i = 0; i < numPlayers; i++)
    {
        if ( shuffle(i, state) < 0 )
        {
            return -1;
        }
    }
    
    //draw player hands
    for (i = 0; i < numPlayers; i++)
    {
        //initialize hand size to zero
        state->handCount[i] = 0;
        state->discardCount[i] = 0;
        //draw 5 cards
        // for (j = 0; j < 5; j++)
        //	{
        //	  drawCard(i, state);
        //	}
    }
    
    //set embargo tokens to 0 for all supply piles
    for (i = 0; i <= treasure_map; i++)
    {
        state->embargoTokens[i] = 0;
    }
    
    //initialize first player's turn
    state->outpostPlayed = 0;
    state->phase = 0;
    state->numActions = 1;
    state->numBuys = 1;
    state->playedCardCount = 0;
    state->whoseTurn = 0;
    state->handCount[state->whoseTurn] = 0;
    //int it; move to top
    
    //Moved draw cards to here, only drawing at the start of a turn
    for (it = 0; it < 5; it++){
        drawCard(state->whoseTurn, state);
    }
    
    updateCoins(state->whoseTurn, state, 0);
    
    return 0;
}
/*------------------------------------
 RNG 0-1
 -----------------------------------*/
double randGen(){
    return  (double)rand()/(double)RAND_MAX;
}
/*************************************
 Main Function
 ************************************/
int main(){
    struct gameState *state = malloc(sizeof(struct gameState));
    struct gameState *state2 = malloc(sizeof(struct gameState));
    assert(state != NULL);
    assert(state2 != NULL);
    srand(time(NULL));
    int players, player, supplyPos, randomSeed, i;
    int kingdom[NUM_K_CARDS];
    for(i=0; i<NUM_TESTS; i++){
        memset(state, 0, sizeof(struct gameState));
        randomSeed = rand();
        players = floor(randGen()*(MAX_PLAYERS-MIN_PLAYERS))+MIN_PLAYERS;
        selectKingdomCards(randomSeed, kingdom);
        initializeGameRandom(players, kingdom, randomSeed, state);
        state->whoseTurn = floor(randGen()*players);
        player = state->whoseTurn;
        state->numBuys = floor(randGen()*4);         //4 is just an arbitrary number of buys
        state->coins = floor(randGen()*10);       //10 coins will allow a buy of anything
        memcpy(state2, state, sizeof(struct gameState));
        supplyPos = floor(randGen()*(treasure_map+1));
        if(buyCard(supplyPos, state) == -1){
            if((state->numBuys <1)
               || (state->supplyCount[supplyPos]<1)
               || (state->coins < getCost(supplyPos))){
                //this is the correct result
            }
            else{
                printf("Test Failed\n");
            }
            continue;
        }
        if((state->coins + getCost(supplyPos)) != state2->coins){
            printf("Coins not updated properly\n");
        }
        if(state->numBuys != (state2->numBuys -1)){
            printf("Number of buys not updated\n");
        }
        if(state->discardCount[player] != state2->discardCount[player]+1){
            printf("Discard count not updated\n");
        }
        if(state->discard[player][state2->discardCount[player]] != supplyPos){
            printf("Test %d: Purchased card not in discard pile\n", i);
            printf("Discard = %d: Purchased Card = %d\n",state->discard[player][state2->discardCount[player]+1], supplyPos);
        }
    }
    
    free(state);
    free(state2);
    return 0;
    
}
